package test;

import com.tofacebook.spring.model.Dept;
import com.tofacebook.spring.model.Emp;
import com.tofacebook.spring.model.EmpInterface;
import com.tofacebook.spring.model.MoreEmp;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;


@Slf4j
public class BeanIdGetClassByIOC {

    /***
     * 从IOC容器中获取我们java bean【类对象】
     * 首先需要使用ClassPathXmlApplicaiotnContext 去加载配置文件
     * 然后通过上面一步获取的IOC容器.getBean(
     * 1.bean的id
     * 2.bean的class类型
     * 3.bean的id 加上的 bean的class类型
     * )
     */


    @Test
    public void getBeanByBeanEquealsId() {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
        //我们通过  class的唯一id获取实例对象是可以从多用Class中获取对应类对象
        // 1.bean的id去获取ioc容器
       /* Emp emp =(Emp)ioc.getBean("emp");
        emp.findEmp();
        log.info("获取的年龄为：{}",emp.getAge());*/

        //2.通过Class类型去获取 ，那么就不知道要获取那个bean
       /* Emp emp = ioc.getBean(Emp.class);//底层他是调用无参构造方法去实例化对象
        log.info("获取的年龄为：{}",emp.getAge());*/

        //3.使用bean的id 和 Class.class类型去加载对象的实例
       /* Emp emp = ioc.getBean("emp",Emp.class);
        emp.findEmp();*/

        //4.使用接口去构造我们父类,交给我们spring IOC容器帮我们构造的
       /* Emp emp = (Emp)ioc.getBean(EmpInterface.class);
        emp.findEmp();*/

        //5.使用接口去实例化接口
        /*EmpInterface empInterface = ioc.getBean(EmpInterface.class);
        empInterface.findEmp();//当我们去调用接口里面方法实际上就是调用实现类里面的方法
        */
        //6.实现接口的类有多个，可不可以使用接口去构造父类呢？？？
        /*Emp em = (Emp)ioc.getBean(EmpInterface.class);
        em.findEmp();

        MoreEmp moreEmp = (MoreEmp)ioc.getBean(EmpInterface.class);
        moreEmp.findEmp();*/
        /**
         * 接口 去构造多个实现的时候会报错，是因为构造的实现类类型不一致导致的
         * 怎么去解决这种方案呢？使用实现类去构造自己。
         */
        Emp em1 = ioc.getBean(Emp.class);
        System.out.println(em1);
        em1.findEmp();

        MoreEmp moreEmp1 = ioc.getBean(MoreEmp.class);
        moreEmp1.findEmp();

    }

    /**
     * 使用依赖注入的方式：setter方式去给对象赋值
     */
    @Test
    public void getEmpByDIBySetter() {
        //获取 spring IOC 容器
        /**
         * new ClassPathXmlApplicationContext("applicationContext.xml");
         * 上面代码的逻辑：通过new 关键字 去构造ClassPathXmlApplicationContext这个对象
         * 传递一个字符串：applicationContext.xml  ，
         * 相当于将xml中配置的bean的信息注入到spring IOC容器里面
         */
        ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
        Emp emp = ioc.getBean(Emp.class);//这是ioc底层使用无参构造方法实例化对象，并且这对象调用set方法去给属性赋值
        System.out.println(emp);  //emp 里面的toString方法
        emp.findEmp();//调用emp里面的findEmp()

    }

    //使用类类型给属性赋值的方式： 使用内部的方式
    @Test
    public void insideClassTypeTOfiledValue() {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
        Emp emp = ioc.getBean(Emp.class);
        System.out.println(emp);

    }

    /**
     * 使用p命名空间来对象来赋值
     */
    @Test
    public void insideClassTypeTOP() {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
        Emp emp = ioc.getBean(Emp.class);
        System.out.println(emp);

    }

    /**
     * 在spring配置文件中引用外部的资源文件
     * 1.首先引入依赖  我们来加载数据库数据源的配置信息
     * 2.在
     */
    @Test
    public void testDataSource() throws SQLException {
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring-datasource.xml");
        DataSource dataSource = ac.getBean(DataSource.class);
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
    }











    @Test
    public void getEmpByPNamespace(){
        //1.获取ioc 容器， new ClassPathXmlApplicationContext(spring配置文件)
        //ApplicationContext  这个叫spring的上下文，也叫spring IOC容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
        Dept dept = ioc.getBean(Dept.class);
        log.info("通过p命名空间去给对象中属性赋值：{}",dept);
    }

}
